#include<bits/stdc++.h>
using namespace std;
bool Miss;
namespace IO{
    const int BUF=1<<21;
    char buff[BUF],*p1=buff,*p2=buff;
    #define gc() (p1==p2&&(p2=((p1=buff)+fread(buff,1,BUF,stdin)),p1==p2)?EOF:*p1++)
    template<typename T>inline void read(T &x){
        char ch=gc();x=0;int f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
        x*=f;
    }
    char obuf[BUF],*p3=obuf;
    inline void pc(char ch){
        if(p3-obuf<BUF) *p3++=ch;
        else fwrite(obuf,p3-obuf,1,stdout),p3=obuf,*p3++=ch;
    }
    inline void put(const char *s){while(*s) pc(*s),++s;}
    char ch[32],ctop;
    template<typename T>inline void print(T x){
    	if(x<0) x=~x+1,pc('-');
        if(!x) return pc(48);
        while(x) ch[++ctop]=x%10^48,x/=10;
        while(ctop) pc(ch[ctop--]);
    }
    inline void flush(){fwrite(obuf,p3-obuf,1,stdout);p3=obuf;}
}
using namespace IO;
const int N=1e5+5;
#define ll long long
const ll inf=-1ll<<59;
int n,m,q,c[N],a[N][5];
struct node{
	ll val,x,y;
	inline bool operator<(node b)const{return val+x+y<b.val+b.x+b.y;}
	inline ll v1(){return val+x;}
	inline ll v2(){return val+y;}
};
struct Tree{
	node a[5][5];
	ll sum[5];
	inline Tree operator+(Tree y){
		node mx1[5],mx2[5];
		for(int i=0;i<m;++i){
			mx1[i].val=inf;
			for(int j=0;j<m;++j) if(a[i][j].v1()>mx1[i].v1()) mx1[i]=a[i][j];
		}
		for(int j=0;j<m;++j){
			mx2[j].val=inf;
			for(int i=0;i<m;++i) if(y.a[i][j].v2()>mx2[j].v2()) mx2[j]=y.a[i][j];
		}
		Tree ans;
		for(int i=0;i<m;++i) ans.sum[i]=sum[i]+y.sum[i];
		for(int i=0;i<m;++i)
		for(int j=0;j<m;++j){
			node now={mx1[i].val+mx2[j].val,mx1[i].x,mx2[j].y};
			now=max(now,(node){a[i][0].v2()+y.a[0][j].v1(),a[i][0].x,y.a[0][j].y});
			if(m>1) now=max(now,(node){a[i][1].v2()+y.a[1][j].v1(),a[i][1].x,y.a[1][j].y});
			if(m>2) now=max(now,(node){a[i][2].v2()+y.a[2][j].v1(),a[i][2].x,y.a[2][j].y});
			if(m>3) now=max(now,(node){a[i][3].v2()+y.a[3][j].v1(),a[i][3].x,y.a[3][j].y});
			if(m>4) now=max(now,(node){a[i][4].v2()+y.a[4][j].v1(),a[i][4].x,y.a[4][j].y});
			ans.a[i][j]=max(now,max((node){a[i][j].val,a[i][j].x,a[i][j].y+y.sum[j]},(node){y.a[i][j].val,y.a[i][j].x+sum[i],y.a[i][j].y}));
		}
		return ans;
	}
	inline ll Max(){
		ll ans=inf;
		for(int i=0;i<m;++i)
		for(int j=0;j<m;++j) ans=max(ans,a[i][j].val);
		return ans;
	}
}t[1<<18];
#define mid ((l+r)>>1)
void build(int p,int l,int r){
	if(l==r){
		for(int i=0;i<m;++i){
			t[p].sum[i]=a[l][i];
			for(int j=0;j<m;++j) t[p].a[i][j].val=inf;
		}
		t[p].a[c[l]][c[l]].val=a[l][c[l]];
		return;
	}
	build(2*p,l,mid);
	build(2*p+1,mid+1,r);
	t[p]=t[2*p]+t[2*p+1];
}
void change(int p,int l,int r,int x){
	if(l==r){
		for(int i=0;i<m;++i){
			t[p].sum[i]=a[l][i];
			for(int j=0;j<m;++j) t[p].a[i][j].val=inf;
		}
		t[p].a[c[l]][c[l]].val=a[l][c[l]];
		return;
	}
	if(x<=mid) change(2*p,l,mid,x);
	else change(2*p+1,mid+1,r,x);
	t[p]=t[2*p]+t[2*p+1];
}
Tree query(int p,int l,int r,int lt,int rt){
	if(lt<=l&&r<=rt) return t[p];
	if(lt<=mid&&mid<rt) return query(2*p,l,mid,lt,rt)+query(2*p+1,mid+1,r,lt,rt);
	return lt<=mid?query(2*p,l,mid,lt,rt):query(2*p+1,mid+1,r,lt,rt);
}
ll ans,op,x,y;
bool SGT;
int main(){
	freopen("paint.in","r",stdin);
	freopen("paint.out","w",stdout);
	cerr<<(double)(&Miss-&SGT)/1024/1024<<"MB\n";
	read(n),read(m),read(q);
	for(int i=1;i<=n;++i) read(c[i]),--c[i];
	for(int i=1;i<=n;++i)
	for(int j=0;j<m;++j) read(a[i][j]);
	build(1,1,n);
	print(ans=t[1].Max()),pc('\n');
	while(q--){
		read(op),read(x),read(y);
		x^=ans,y^=ans;
		if(op==1) c[x]=y-1,change(1,1,n,x);
		else print(ans=query(1,1,n,x,y).Max()),pc('\n');
	}
	flush();
	return 0;
}


